﻿using System;
using System.Collections.Generic;
using System.Text;

namespace AI_BOTS
{
	public static class PlanetFactory
	{
		public enum PLANET_TYPES
		{
			MINE,
			ENEMY,
			NUERTAL,
			BOTH
		}

		private static List<Planet> GetPlanetsByType(PlanetWars pw, PLANET_TYPES planetType)
		{
			List<Planet> returnData = new List<Planet>();

			switch(planetType)
			{
				case PLANET_TYPES.MINE:
					returnData = pw.MyPlanets();
					break;
				case PLANET_TYPES.ENEMY:
					returnData = pw.EnemyPlanets();
					break;
				case PLANET_TYPES.BOTH:
					returnData = pw.NotMyPlanets();
					break;
				case PLANET_TYPES.NUERTAL:
					returnData = pw.NeutralPlanets();
					break;
			}
			return returnData;
		}

		public static List<Planet> FetchPlanetsByStrength(PlanetWars pw, PlanetFactory.PLANET_TYPES planetType, bool strongestFirst, int? maxPlanets)
		{
			List<Planet> resultsFinal = new List<Planet>();
			List<Planet> results = GetPlanetsByType(pw, planetType);

			if(strongestFirst)
				results.Sort(delegate(Planet p1, Planet p2) { return p2.NumShips.CompareTo(p1.NumShips); });
			else
				results.Sort(delegate(Planet p1, Planet p2) { return p1.NumShips.CompareTo(p2.NumShips); });

			return Take(results, maxPlanets);
		}

		public static List<Planet> FetchPlanetsByDistance(PlanetWars pw, int sourcePlanet, PLANET_TYPES planetType, bool closestFirst, int? maxPlanets)
		{
			List<KeyValuePair<int, int>> results = new List<KeyValuePair<int, int>>();
			List<Planet> resultsFinal = new List<Planet>();

			foreach(Planet p in GetPlanetsByType(pw, planetType))
			{
				results.Add(new KeyValuePair<int, int>(p.PlanetID, pw.Distance(sourcePlanet, p.PlanetID)));
			}

			if(closestFirst)
				results.Sort(delegate(KeyValuePair<int, int> first, KeyValuePair<int, int> second) { return first.Value.CompareTo(second.Value); });
			else
				results.Sort(delegate(KeyValuePair<int, int> first, KeyValuePair<int, int> second) { return second.Value.CompareTo(first.Value); });

			List<Planet> sortedPlanets = new List<Planet>();

			foreach(KeyValuePair<int, int> k in results)
			{
				sortedPlanets.Add(pw.GetPlanet(k.Key));
			}
			return Take(sortedPlanets, maxPlanets);
		}

		public static List<Planet> FetchPlanetsByGrowthRate(PlanetWars pw, PLANET_TYPES planetType, bool closestFirst, int? maxPlanets)
		{
			List<Planet> resultsFinal = new List<Planet>();
			List<Planet> results = GetPlanetsByType(pw, planetType);

			if(closestFirst)
				results.Sort(delegate(Planet p1, Planet p2) { return p2.GrowthRate.CompareTo(p1.GrowthRate); });
			else
				results.Sort(delegate(Planet p1, Planet p2) { return p1.GrowthRate.CompareTo(p2.GrowthRate); });

			return Take(results, maxPlanets);
		}

		public static List<Planet> FetchBestAttackOrder(PlanetWars pw, int sourcePlanet, PLANET_TYPES planetType, int? maxPlanets)
		{
			// based on distance and fleets
			List<KeyValuePair<int, int>> results = new List<KeyValuePair<int, int>>();

			foreach(Planet p in GetPlanetsByType(pw, planetType))
			{
				results.Add(new KeyValuePair<int, int>(p.PlanetID, p.NumShips + pw.Distance(sourcePlanet, p.PlanetID) - (p.GrowthRate)));
			}

			// smallest on top
			results.Sort(delegate(KeyValuePair<int, int> first, KeyValuePair<int, int> second) { return first.Value.CompareTo(second.Value); });

			List<Planet> sortedPlanets = new List<Planet>();
			foreach(KeyValuePair<int, int> k in results)
			{
				sortedPlanets.Add(pw.GetPlanet(k.Key));
			}

			return Take(sortedPlanets, maxPlanets);
		}

		private static List<Planet> Take(List<Planet> planets, int? amount)
		{
			if(amount == null)
				return planets;

			List<Planet> results = new List<Planet>();
			for(int i = 0;i < amount;i++)
			{
				results.Add(planets[i]);
			}
			return results;
		}
	}
}
